/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.xml.parser;

import java.lang.reflect.Field;
import java.util.List;

import org.w3c.dom.Node;
import org.zhiqim.kernel.ZhiqimI18n;
import org.zhiqim.kernel.util.Annotations;
import org.zhiqim.kernel.util.Asserts;
import org.zhiqim.kernel.util.Classes;
import org.zhiqim.kernel.util.Strings;
import org.zhiqim.kernel.util.Validates;
import org.zhiqim.kernel.xml.Xml;
import org.zhiqim.kernel.xml.XmlParser;
import org.zhiqim.kernel.xml.XmlTag;
import org.zhiqim.kernel.xml.Xmls;

/**
 * 对象适配器，不包括基本类型、数组类型
 *
 * @version v1.1.2 @author zouzhigang 2015-8-21 新建与整理
 */
public class ObjectParser implements XmlParser
{
    private Xml xmlMain;
    
    @Override
    public XmlParser set(Xml xmlMain)
    {
        this.xmlMain = xmlMain;
        return this;
    }
    
    @Override
    public String toStringInner(Object obj, String tagName, int tagLevel)
    {//类对象，以自己的标记为准，不采用字段的标记
        
        Class<?> clazz = obj.getClass();
        if (tagName == null && (obj instanceof XmlTag))
            tagName = ((XmlTag)obj).getXmlTag();
        
        if (tagName == null)
            tagName = Xmls.getXmlClassTag(clazz);
        
        Asserts.as(Validates.isNotEmptyBlank(tagName)?null:"对象转XML时未定义XmlClassTag");
        
        StringBuilder strb = new StringBuilder();
        Strings.addNewLine(strb);
        Strings.addTwoSpace(strb, tagLevel);
        Xmls.addTagBegin(strb, tagName);
        
        List<Field> fieldList = Classes.getFieldListDeep(clazz);
        for (Field field : fieldList)
        {
            String name = Annotations.getFieldName(field);
            Object value = Classes.getFieldValue(obj, field);
            if (value == null)
                continue;//为null不传入
            
            boolean hasGroup = Xmls.hasXmlFieldGroup(field);
            strb.append(xmlMain.toStringInner(value, hasGroup?name:null, hasGroup?tagLevel+1:tagLevel));
        }

        Strings.addNewLine(strb);
        Strings.addTwoSpace(strb, tagLevel);
        Xmls.addTagEnd(strb, tagName);
        return strb.toString();
    }

    @Override
    public Object toObjectInner(Node node, Class<?> cls, Class<?> generics)
    {
        String tag = Xmls.getXmlClassTag(cls);
        if (!Xmls.isOwn(node, tag))
            return null;
        
        Object obj = Classes.newInstance(cls);
        Asserts.assertNotNull(obj, ZhiqimI18n.classDoesNotSupportNoParameterConstructors);
        
        List<Field> fieldList = Classes.getFieldListDeep(cls);
        for (Field field : fieldList)
        {
            Class<?> fieldClass = field.getType();
            String fieldName = Annotations.getFieldName(field);
            Class<?> fieldGenerics = Annotations.getGenericsClass(field);
            
            //判断是否有组号，如果有则取组号下内容，默认都有组号，没有则还是在node下
            Node fieldNode = Xmls.hasXmlFieldGroup(field)?Xmls.getNode(node, fieldName):node;
            Object value = xmlMain.toObjectInner(fieldNode, fieldClass, fieldGenerics);
            Classes.setFieldValue(obj, field, value);
        }
        
        return obj;
    }
}
